package com.hzncc.flowable_diboot.delivery.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.diboot.core.binding.Binder;
import com.diboot.core.binding.QueryBuilder;
import com.diboot.core.holder.ThreadLocalHolder;
import com.diboot.core.util.S;
import com.diboot.core.util.V;
import com.diboot.core.vo.Pagination;
import com.hzncc.flowable_diboot.contract.entity.*;
import com.hzncc.flowable_diboot.contract.service.*;
import com.hzncc.flowable_diboot.contract.vo.*;
import com.hzncc.flowable_diboot.delivery.dto.DeliveryFormDTO;
import com.hzncc.flowable_diboot.delivery.dto.DeliveryRegisterDTO;
import com.hzncc.flowable_diboot.delivery.entity.DeliveryDetail;
import com.hzncc.flowable_diboot.delivery.entity.DeliveryProduct;
import com.hzncc.flowable_diboot.delivery.service.DeliveryDetailService;
import com.hzncc.flowable_diboot.delivery.service.DeliveryInfoService;
import com.hzncc.flowable_diboot.delivery.service.DeliveryProductService;
import com.hzncc.flowable_diboot.delivery.vo.*;
import com.hzncc.flowable_diboot.entity.SapCustomer;
import com.hzncc.flowable_diboot.enums.RegisterTypeEnum;
import com.hzncc.flowable_diboot.exception.BusinessException;
import com.hzncc.flowable_diboot.exception.SapException;
import com.hzncc.flowable_diboot.project_contracts.entity.ProjectContractAudit;
import com.hzncc.flowable_diboot.project_contracts.entity.ProjectSamContract;
import com.hzncc.flowable_diboot.project_contracts.service.ProjectContractAuditService;
import com.hzncc.flowable_diboot.service.SapCustomerService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import com.diboot.core.service.impl.BaseServiceImpl;

import com.hzncc.flowable_diboot.delivery.entity.DeliveryRegister;
import com.hzncc.flowable_diboot.mapper.DeliveryRegisterMapper;
import com.hzncc.flowable_diboot.delivery.service.DeliveryRegisterService;
import org.springframework.transaction.annotation.Transactional;

import jakarta.annotation.Resource;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;


/**
 * 发货登记 相关Service实现类
 *
 * @author MyName
 * @version 1.0
 * @date 2024-09-29
 * Copyright © MyCorp
 */
@Slf4j
@Service
public class DeliveryRegisterServiceImpl extends BaseServiceImpl<DeliveryRegisterMapper, DeliveryRegister> implements DeliveryRegisterService {

    @Resource
    private DeliveryProductService deliveryProductService;

    @Resource
    private DeliveryInfoService deliveryInfoService;

    @Resource
    private DeliveryDetailService deliveryDetailService;

    @Resource
    private SalesContractService salesContractService;

    @Resource
    private SalesContractExtService salesContractExtService;

    @Resource
    private SalesContractMrlService salesContractMrlService;

    @Resource
    private ContractAuditService contractAuditService;

    @Resource
    private ProjectContractAuditService projectContractAuditService;

    @Resource
    private DeliveryRegisterMapper deliveryRegisterMapper;

    @Override
    public List<DeliveryFormVO> getDeliveryForms(DeliveryFormDTO deliveryFormDTO) {
        List<DeliveryRegister> deliveryRegisters = deliveryRegisterMapper.getDeliveryForms(deliveryFormDTO);
        return Binder.convertAndBindRelations(deliveryRegisters, DeliveryFormVO.class);
    }

    @Override
    public List<DeliveryFormVO> getDeliveryForms(DeliveryFormDTO deliveryFormDTO, Pagination pagination) {
        Page<Object> page = pagination.toPage(DeliveryRegister.class);
        List<DeliveryRegister> deliveryRegisters = deliveryRegisterMapper.getDeliveryForms(deliveryFormDTO, page);
        List<DeliveryFormVO> deliveryFormVOS = Binder.convertAndBindRelations(deliveryRegisters, DeliveryFormVO.class);
        pagination.setTotalCount(page.getTotal());
        return deliveryFormVOS;
    }

    @Override
    @Transactional
    public Boolean syncDeliveryRegister(List<SyncDeliveryRegisterVO> syncDeliveryRegisterVOList) {
        if (CollectionUtils.isEmpty(syncDeliveryRegisterVOList)) {
            throw new SapException("推送数据为空");
        }
        //按照发货编码分组
        Map<String, List<SyncDeliveryRegisterVO>> deliveryCodeToSyncMap = syncDeliveryRegisterVOList.stream().collect(Collectors.groupingBy(SyncDeliveryRegisterVO::getSapDeliveryCode));
        //无特殊情况,发货单号应该唯一
        Set<String> deliveryCodes = deliveryCodeToSyncMap.keySet();
        for (String deliveryCode : deliveryCodes) {
            if (StringUtils.isEmpty(deliveryCode)) {
                throw new SapException("发货单号为空");
            }

            String registerType = RegisterTypeEnum.normal.getCode();//默认常规发货登记
            List<SyncDeliveryRegisterVO> syncDeliveryRegisterVOS = deliveryCodeToSyncMap.get(deliveryCode);
            //根据合同项目号和物料编码分组
            Map<String, SyncDeliveryRegisterVO> mrlCodeToSync = syncDeliveryRegisterVOS.stream().collect(Collectors.groupingBy(item -> item.getSapContractItem().replaceFirst("^0+", "") + "#" + item.getMrlCode(), Collectors.collectingAndThen(Collectors.toList(), list -> list.get(0))));
            SyncDeliveryRegisterVO syncDeliveryRegister = syncDeliveryRegisterVOS.get(0);
            String sapContractCode = syncDeliveryRegister.getSapCode();
            String sapOrderCode = syncDeliveryRegister.getSapOrderCode();
            LocalDateTime deliveryTime = syncDeliveryRegister.getDeliveryTime();
            String delFlag = syncDeliveryRegister.getDelFlag();
            // 销售合同信息
            LambdaQueryWrapper<SalesContract> salesContractQuery = new LambdaQueryWrapper<>();
            salesContractQuery.eq(SalesContract::getSapCode, sapContractCode);
            // 设置忽略拦截器
            ThreadLocalHolder.setIgnoreInterceptor();
            SalesContractListVO salesContract = salesContractService.getViewObject(salesContractQuery, SalesContractListVO.class);
            if (ObjectUtils.isEmpty(salesContract)) {
                throw new SapException("Sap合同不存在");
            }
            SalesContractExt salesContractExt = salesContract.getExt();
            //销售合同物料明细
            List<SalesContractMrl> salesContractMrlList = salesContract.getMrlList();
            //客户信息
            SapCustomer sapCustomer = salesContract.getSapCustomer();
            //合同项目
            ContractProduct contractProduct = salesContract.getProduct();
            //项目类合同产品供销合同
            ProjectSamContract projectSamContract = salesContract.getProjectSamContract();
            BigDecimal productPrice = new BigDecimal(0);
            if (StringUtils.isNotEmpty(salesContract.getProjectContractId()) && ObjectUtils.isNotEmpty(projectSamContract)) {
                productPrice = projectSamContract.getTotal();
            } else if (ObjectUtils.isNotEmpty(contractProduct)) {
                productPrice = contractProduct.getProductPrice();
            }
            if ("1".equals(delFlag)) {
                //冲销发货登记
                registerType = RegisterTypeEnum.reversal.getCode();
                LambdaUpdateWrapper<DeliveryRegister> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper.set(DeliveryRegister::getRegisterType, registerType).eq(DeliveryRegister::getDeliveryCode, deliveryCode);
                // 设置忽略拦截器
                ThreadLocalHolder.setIgnoreInterceptor();
                this.update(updateWrapper);
                LambdaUpdateWrapper<DeliveryDetail> detailUpdate = new LambdaUpdateWrapper<>();
                detailUpdate.set(DeliveryDetail::getRegisterType, registerType).eq(DeliveryDetail::getDeliveryCode, deliveryCode);
                ThreadLocalHolder.setIgnoreInterceptor();
                deliveryDetailService.updateEntity(detailUpdate);
            }
            //过往发货明细,查询当前合同下所有的发货登记（不包括冲销登记）
            LambdaQueryWrapper<DeliveryRegister> deliveryQuery = new LambdaQueryWrapper<>();
            deliveryQuery.eq(DeliveryRegister::getSapContractCode, sapContractCode).ne(DeliveryRegister::getRegisterType, RegisterTypeEnum.reversal.getCode()).eq(DeliveryRegister::isDeleted, 0);
            // 设置忽略拦截器
            ThreadLocalHolder.setIgnoreInterceptor();
            List<DeliveryRegister> entityList = this.getEntityList(deliveryQuery);
            List<String> codes = entityList.stream().map(DeliveryRegister::getDeliveryCode).collect(Collectors.toList());
            ArrayList<DeliveryDetail> oldDeliveryDetails = new ArrayList<>();
            if (CollectionUtils.isNotEmpty(codes)) {
                LambdaQueryWrapper<DeliveryDetail> detailQuery = new LambdaQueryWrapper<>();
                detailQuery.eq(DeliveryDetail::getType, "1").in(DeliveryDetail::getRegisterType, "1", "2").in(DeliveryDetail::getDeliveryCode, codes);
                // 设置忽略拦截器
                ThreadLocalHolder.setIgnoreInterceptor();
                List<DeliveryDetail> oldDeliveryDetailList = deliveryDetailService.getEntityList(detailQuery);
                oldDeliveryDetails = new ArrayList<>(oldDeliveryDetailList);
            }
            ArrayList<DeliveryDetail> deliveryDetailList = new ArrayList<>();
            if ("0".equals(delFlag)) {
                LambdaQueryWrapper<DeliveryRegister> infoQuery = new LambdaQueryWrapper<>();
                infoQuery.eq(DeliveryRegister::getDeliveryCode, deliveryCode);
                ThreadLocalHolder.setIgnoreInterceptor();
                DeliveryRegister viewObject = this.getSingleEntity(infoQuery);
                if (ObjectUtils.isNotEmpty(viewObject)) {
                    ThreadLocalHolder.setIgnoreInterceptor();
                    this.deleteEntity("delivery_code", deliveryCode);
                    ThreadLocalHolder.setIgnoreInterceptor();
                    deliveryProductService.deleteEntity("delivery_code", deliveryCode);
                    ThreadLocalHolder.setIgnoreInterceptor();
                    deliveryDetailService.deleteEntity("delivery_code", deliveryCode);
                }
                //发货登记信息
                DeliveryRegister deliveryRegister = new DeliveryRegister();
                deliveryRegister.setTenantId(salesContract.getTenantId()).setRegistered("0").setRegisterType(registerType).setSapContractCode(sapContractCode)
                        .setSapOrderCode(sapOrderCode).setDeliveryCode(deliveryCode).setSapDeliveryTime(deliveryTime).setPlanDeliveryTime(salesContractExt.getPlannedDeliveryTime().atStartOfDay());
                if (StringUtils.isEmpty(salesContract.getProjectContractId())) {
                    deliveryRegister.setReviewCategory("0");
                } else {
                    deliveryRegister.setReviewCategory("1");
                }
                BigDecimal deliveryAmount = syncDeliveryRegisterVOList.stream().map(SyncDeliveryRegisterVO::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                deliveryRegister.setDeliveryAmount(deliveryAmount);

                String singer = "";
                String finalUser = "";
                String consigneeName = "";
                if (StringUtils.isNotEmpty(salesContract.getProjectContractId())) {
                    LambdaQueryWrapper<ProjectContractAudit> projectContractAuditQuery = new LambdaQueryWrapper<>();
                    projectContractAuditQuery.eq(ProjectContractAudit::getContractCode, salesContract.getOrderCode()).ne(ProjectContractAudit::getContractStatus, 0).eq(ProjectContractAudit::isDeleted, 0);
                    ThreadLocalHolder.setIgnoreInterceptor();
                    List<ProjectContractAudit> projectContractList = projectContractAuditService.getEntityList(projectContractAuditQuery);
                    ProjectContractAudit projectContractDetailByCode = projectContractList.stream().max(Comparator.comparing(ProjectContractAudit::getContractVersion)).get();
                    singer = projectContractDetailByCode.getSigner();
                } else {
                    LambdaQueryWrapper<ContractAudit> contractAuditQuery = new LambdaQueryWrapper<>();
                    contractAuditQuery.eq(ContractAudit::getContractCode, salesContract.getOrderCode()).ne(ContractAudit::getContractStatus, 0).eq(ContractAudit::isDeleted, 0);
                    ThreadLocalHolder.setIgnoreInterceptor();
                    List<ContractAudit> contractList = contractAuditService.getEntityList(contractAuditQuery);
                    ContractAudit contractDetailByCode = contractList.stream().max(Comparator.comparing(ContractAudit::getContractVersion)).get();
                    ThreadLocalHolder.setIgnoreInterceptor();
                    ContractAuditVO contractAuditVO = Binder.convertAndBindRelations(contractDetailByCode, ContractAuditVO.class);
                    singer = contractDetailByCode.getSigner();
                    finalUser = contractDetailByCode.getFinalUser();
                    if (ObjectUtils.isNotEmpty(contractAuditVO.getContractExtVO()) && StringUtils.isNotEmpty(contractAuditVO.getContractExtVO().getConsigneeName())) {
                        consigneeName = contractAuditVO.getContractExtVO().getConsigneeName();
                    }
                }

                deliveryRegister.setConsigneeName(consigneeName);
                // 设置忽略拦截器
                ThreadLocalHolder.setIgnoreInterceptor();
                this.saveOrUpdate(deliveryRegister);
                DeliveryProduct deliveryProduct = new DeliveryProduct();
                deliveryProduct.setTenantId(salesContract.getTenantId())
                        .setDeliveryCode(deliveryCode)
                        .setSapContractCode(sapContractCode)
                        .setContractCode(salesContract.getOrderCode())
                        .setContractType(salesContract.getContractType())
                        .setRecipient(salesContract.getRecipient())
                        .setSalesTerritory(ObjectUtils.isNotEmpty(salesContract.getSalesTerritory()) ? salesContract.getSalesTerritory() : "")
                        .setBusinessModel(ObjectUtils.isNotEmpty(salesContract.getBusinessModel()) ? salesContract.getBusinessModel() : "")
                        .setBusinessDept(salesContract.getBusinessDept())
                        .setSigner(singer)
                        .setProvince(ObjectUtils.isNotEmpty(sapCustomer) ? sapCustomer.getProvince() : "")
                        .setCity("")
                        .setOrderModel(salesContract.getOrderModel())
                        .setMachineToolType(ObjectUtils.isNotEmpty(salesContractExt) && ObjectUtils.isNotEmpty(salesContractExt.getMachineToolType()) ? salesContractExt.getMachineToolType() : "")
                        .setSupportingMachineTool(ObjectUtils.isNotEmpty(salesContractExt) && ObjectUtils.isNotEmpty(salesContractExt.getSupportingMachineTool()) ? salesContractExt.getSupportingMachineTool() : "")
                        .setProductSeries("")
                        .setGrade(ObjectUtils.isNotEmpty(salesContractExt) && ObjectUtils.isNotEmpty(salesContractExt.getGrade()) ? salesContractExt.getGrade() : "")
                        .setProductCount(StringUtils.isNotEmpty(salesContract.getOrderQuantity()) ? Long.parseLong(salesContract.getOrderQuantity()) : 0L)
                        .setProductPrice(productPrice)
                        .setSignDate(salesContract.getOrderDate())
                        .setDeliveryTime(ObjectUtils.isNotEmpty(salesContract.getDeliveryTime()) ? salesContract.getDeliveryTime() : "")
                        .setAccountAssignment(ObjectUtils.isNotEmpty(sapCustomer) ? sapCustomer.getDis() : "")
                        .setFinalUser(finalUser);
                // 设置忽略拦截器
                ThreadLocalHolder.setIgnoreInterceptor();
                deliveryProductService.createEntity(deliveryProduct);

                //发货明细
                for (SyncDeliveryRegisterVO syncDeliveryRegisterVO : syncDeliveryRegisterVOS) {
                    DeliveryDetail deliveryDetail = new DeliveryDetail();
                    deliveryDetail.setTenantId(salesContract.getTenantId())
                            .setRegisterType("1")
                            .setSapContractCode(sapContractCode)
                            .setSapOrderCode(sapOrderCode)
                            .setDeliveryCode(syncDeliveryRegisterVO.getSapDeliveryCode())
                            .setType("1").setMaterialCode(syncDeliveryRegisterVO.getMrlCode())
                            .setPrice(syncDeliveryRegisterVO.getPrice())
                            .setQuantity(syncDeliveryRegisterVO.getQuantity().longValue())
                            .setAmount(syncDeliveryRegisterVO.getAmount())
                            .setDescription(syncDeliveryRegisterVO.getMrlDesc())
                            .setProductCode(syncDeliveryRegisterVO.getSapContractItem().replaceFirst("^0+", ""));
                    deliveryDetailList.add(deliveryDetail);
                }
                oldDeliveryDetails.addAll(deliveryDetailList);
            }
            //缺货明细，按照物料分组求和
            Map<String, Long> collect = oldDeliveryDetails.stream().collect(Collectors.groupingBy(item -> item.getProductCode() + "#" + item.getMaterialCode(), Collectors.summingLong(DeliveryDetail::getQuantity)));
            ArrayList<DeliveryDetail> outDeliveryDetailsList = new ArrayList<>();
            for (SalesContractMrl salesContractMrl : salesContractMrlList) {
                if (ObjectUtils.isNotEmpty(salesContractMrl) && ObjectUtils.isNotEmpty(mrlCodeToSync.get(salesContractMrl.getProductName() + "#" + salesContractMrl.getMrlCode()))) {
                    LambdaUpdateWrapper<SalesContractMrl> salesContractMrlUpdate = new LambdaUpdateWrapper<>();
                    BigDecimal qtyShipped = new BigDecimal(0);
                    BigDecimal amount = new BigDecimal(0);
                    String shippingStatus = "0";
                    if (ObjectUtils.isNotEmpty(collect.get(salesContractMrl.getProductName() + "#" + salesContractMrl.getMrlCode()))) {
                        qtyShipped = BigDecimal.valueOf(collect.get(salesContractMrl.getProductName() + "#" + salesContractMrl.getMrlCode()));
                    }
                    if (ObjectUtils.isNotEmpty(mrlCodeToSync.get(salesContractMrl.getProductName() + "#" + salesContractMrl.getMrlCode()))) {
                        amount = oldDeliveryDetails.stream().filter(item -> item.getProductCode().equals(salesContractMrl.getProductName()) && item.getMaterialCode().equals(salesContractMrl.getMrlCode())).map(DeliveryDetail::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                    }
                    BigDecimal qtyUnshipped = salesContractMrl.getTargerQty().subtract(qtyShipped);
                    if (qtyUnshipped.compareTo(BigDecimal.ZERO) > 0) {
                        shippingStatus = "2";
                    }
                    if (qtyUnshipped.compareTo(salesContractMrl.getTargerQty()) == 0) {
                        shippingStatus = "1";
                    }
                    salesContractMrlUpdate.set(SalesContractMrl::getQtyShipped, qtyShipped)
                            .set(SalesContractMrl::getQtyUnshipped, qtyUnshipped)
                            .set(SalesContractMrl::getAmount, amount)
                            .set(SalesContractMrl::getShippingStatus, shippingStatus)
                            .eq(SalesContractMrl::getId, salesContractMrl.getId());
                    ThreadLocalHolder.setIgnoreInterceptor();
                    salesContractMrlService.updateEntity(salesContractMrlUpdate);

                }
                if (salesContractMrl.getDeletedFlag()) {
                    continue;
                }
                DeliveryDetail deliveryDetail = new DeliveryDetail();
                BigDecimal targetQty = salesContractMrl.getTargerQty();//目标数量
                deliveryDetail.setTenantId(salesContract.getTenantId())
                        .setRegisterType("1")
                        .setSapContractCode(sapContractCode)
                        .setSapOrderCode(sapOrderCode)
                        .setDeliveryCode(deliveryCode)
                        .setType("2").setMaterialCode(salesContractMrl.getMrlCode())
                        .setDescription(salesContractMrl.getMrlDesc())
                        .setProductCode(salesContractMrl.getProductName());
                if (!collect.containsKey(salesContractMrl.getProductName() + "#" + salesContractMrl.getMrlCode())) {
                    //该物料全部缺货
                    deliveryDetail.setQuantity(targetQty.longValue());
                    outDeliveryDetailsList.add(deliveryDetail);
                    deliveryDetailList.add(deliveryDetail);
                } else {
                    BigDecimal quantity = BigDecimal.valueOf(collect.get(salesContractMrl.getProductName() + "#" + salesContractMrl.getMrlCode()));//已发货数量
                    if (targetQty.compareTo(quantity) > 0) {
                        //该物料部分缺货
                        deliveryDetail.setQuantity(targetQty.subtract(quantity).longValue());
                        outDeliveryDetailsList.add(deliveryDetail);
                        deliveryDetailList.add(deliveryDetail);
                    }
                }
            }
            // 设置忽略拦截器
            ThreadLocalHolder.setIgnoreInterceptor();
            deliveryDetailService.createEntities(deliveryDetailList);
            LambdaUpdateWrapper<SalesContract> salesContractUpdate = new LambdaUpdateWrapper<>();
            if (CollectionUtils.isNotEmpty(outDeliveryDetailsList)) {
                salesContractUpdate.set(SalesContract::getDeliveryStatus, "2").eq(SalesContract::getId, salesContract.getId());
            } else {
                salesContractUpdate.set(SalesContract::getDeliveryStatus, "0").eq(SalesContract::getId, salesContract.getId());
            }
            ThreadLocalHolder.setIgnoreInterceptor();
            salesContractService.updateEntity(salesContractUpdate);
        }
        return true;
    }

    @Override
    @Transactional
    public Boolean batchProjectSupplement(DeliveryRegisterVO deliveryRegisterVO) {
        List<String> batchIds = deliveryRegisterVO.getBatchIds();
//        List<DeliveryRegister> entityListByIds = this.getEntityListByIds(batchIds);
//        List<String> deliveryCodes = entityListByIds.stream().map(DeliveryRegister::getDeliveryCode).collect(Collectors.toList());
        LambdaUpdateWrapper<DeliveryRegister> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(DeliveryRegister::getDeliverySituation, deliveryRegisterVO.getDeliverySituation())
                .set(DeliveryRegister::getRegistered, "1")
                .in(DeliveryRegister::getId, batchIds);
        this.updateEntity(updateWrapper);
//        List<String> sapContractCodes = entityListByIds.stream().map(DeliveryRegister::getSapContractCode).collect(Collectors.toList());
//        LambdaUpdateWrapper<SalesContract> salesContractUpdateWrapper = new LambdaUpdateWrapper<>();
//        salesContractUpdateWrapper.set(SalesContract::getDeliveryStatus,deliveryRegisterVO.getDeliverySituation()).in(SalesContract::getSapCode,sapContractCodes);
//        salesContractService.updateEntity(salesContractUpdateWrapper);
        return true;
    }

    @Override
    @Transactional
    public Boolean batchSysSupplement(DeliveryRegisterVO deliveryRegisterVO) {
        List<String> batchIds = deliveryRegisterVO.getBatchIds();
        LambdaUpdateWrapper<DeliveryRegister> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(DeliveryRegister::getQuoteDeliveryCode, deliveryRegisterVO.getQuoteDeliveryCode())
                .set(DeliveryRegister::getDeliveryTime, deliveryRegisterVO.getDeliveryTime())
                .set(DeliveryRegister::getPlanDeliveryTime, deliveryRegisterVO.getPlanDeliveryTime())
                .set(DeliveryRegister::getDelaied, deliveryRegisterVO.getDelaied())
                .set(DeliveryRegister::getDelayDays, deliveryRegisterVO.getDelayDays())
                .set(DeliveryRegister::getTransitCompany, deliveryRegisterVO.getTransitCompany())
                .set(DeliveryRegister::getQuantity, deliveryRegisterVO.getQuantity())
                .set(DeliveryRegister::getWeight, deliveryRegisterVO.getWeight())
                .set(DeliveryRegister::getCompleteSet, deliveryRegisterVO.getCompleteSet())
                .set(DeliveryRegister::getBillCode, deliveryRegisterVO.getBillCode())
                .set(DeliveryRegister::getConsigneeName, deliveryRegisterVO.getConsigneeName())
                .set(DeliveryRegister::getRemark, deliveryRegisterVO.getRemark())
                .set(DeliveryRegister::getRegistered, "1")
                .in(DeliveryRegister::getId, batchIds);
        this.update(updateWrapper);
        return true;
    }

    @Override
    public DeliveryRegisterVO getDeliveryInfoByDeliveryCode(String deliveryCode) {
        LambdaQueryWrapper<DeliveryRegister> infoQuery = new LambdaQueryWrapper<>();
        infoQuery.eq(DeliveryRegister::getDeliveryCode, deliveryCode);
        return this.getViewObject(infoQuery, DeliveryRegisterVO.class);
    }

    @Override
    public Map<String, String> getDeliveryCodeList(String registerType) {
        Map<String, String> result = new HashMap<>();
        LambdaQueryWrapper<DeliveryRegister> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StringUtils.isNotEmpty(registerType), DeliveryRegister::getRegisterType, registerType).eq(DeliveryRegister::isDeleted, 0);
        List<DeliveryRegister> entityList = this.getEntityList(queryWrapper);
        if (!CollectionUtils.isEmpty(entityList)) {
            result = entityList.stream().collect(Collectors.toMap(DeliveryRegister::getId, DeliveryRegister::getDeliveryCode));
        }
        return result;
    }

    @Override
    public List<DeliveryRegisterVO> getPage(DeliveryRegisterDTO deliveryRegisterDTO, Pagination pagination) {
        if ("1".equals(deliveryRegisterDTO.getMustSapContractCode()) && StringUtils.isEmpty(deliveryRegisterDTO.getSapContractCode())) {
            return new ArrayList<>();
        }
        String contractCode = deliveryRegisterDTO.getContractCode();
        // 避免wrapper里生成contractCode
        deliveryRegisterDTO.setContractCode(null);
        QueryWrapper<DeliveryRegister> queryWrapper = QueryBuilder.toQueryWrapper(deliveryRegisterDTO);
        pagination.setOrderBy("sapDeliveryTime:DESC,createTime:DESC,sapContractCode:DESC,sapOrderCode:DESC");
        if (pagination != null && V.isEmpty(pagination.getOrderBy())) {
            pagination.setOrderBy(Pagination.ORDER_BY_ID_DESC);
        }
        // 模糊查询合同编号
        if (S.isNotBlank(contractCode)) {
            List<DeliveryProduct> dp = deliveryProductService.lambdaQuery().select(DeliveryProduct::getDeliveryCode).like(DeliveryProduct::getContractCode, contractCode).list();
            if (dp != null && dp.size() > 0) {
                queryWrapper.lambda().in(DeliveryRegister::getDeliveryCode, dp.stream().map(DeliveryProduct::getDeliveryCode).collect(Collectors.toList()));
            }
        }

        return this.getViewObjectList(queryWrapper, pagination, DeliveryRegisterVO.class);
    }

    @Override
    public DeliveryRegisterVO getDetail(String id) {
        DeliveryRegisterVO viewObject = this.getViewObject(id, DeliveryRegisterVO.class);
        if (ObjectUtils.isEmpty(viewObject)) {
            throw new BusinessException("发货登记信息不存在");
        }
        return viewObject;
    }

    @Override
    @Transactional
    public Boolean saveDeliveryRegister(DeliveryRegisterVO deliveryRegisterDetailVO) {
        String deliveryCode = deliveryRegisterDetailVO.getDeliveryCode();
        String registerType = deliveryRegisterDetailVO.getRegisterType();
        if (StringUtils.isEmpty(deliveryCode) && RegisterTypeEnum.abnormal.getCode().equals(deliveryRegisterDetailVO.getRegisterType())) {
            deliveryCode = genDeliveryCode();
            deliveryRegisterDetailVO.setDeliveryCode(deliveryCode);
        } else {
            throw new BusinessException("发货单号为空");
        }
        LambdaQueryWrapper<DeliveryRegister> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DeliveryRegister::getDeliveryCode, deliveryCode).eq(DeliveryRegister::isDeleted, 0);
        List<DeliveryRegister> entityList = this.getEntityList(queryWrapper);
        if (CollectionUtils.isNotEmpty(entityList)) {
            throw new BusinessException("发货单号已存在,新增失败!");
        }
        boolean success = this.createEntity(deliveryRegisterDetailVO);
        DeliveryProductDetailVO product = deliveryRegisterDetailVO.getProduct();
        if (ObjectUtils.isNotEmpty(product)) {
            product.setDeliveryCode(deliveryCode);
            deliveryProductService.createEntity(product);
        }
        List<DeliveryDetail> detailDetailVOS = new ArrayList<>();
        List<DeliveryDetailDetailVO> deliveryDetails = deliveryRegisterDetailVO.getDeliveryDetail();
        if (CollectionUtils.isNotEmpty(deliveryDetails)) {
            String finalDeliveryCode = deliveryCode;
            List<DeliveryDetail> collect = deliveryDetails.stream().map(item -> item.setDeliveryCode(finalDeliveryCode).setRegisterType(registerType).setType("1")).collect(Collectors.toList());
            detailDetailVOS.addAll(collect);
        }
        List<DeliveryDetailDetailVO> outDeliveryDetails = deliveryRegisterDetailVO.getOutDeliveryDetail();
        if (CollectionUtils.isNotEmpty(outDeliveryDetails)) {
            String finalDeliveryCode = deliveryCode;
            List<DeliveryDetail> collect = outDeliveryDetails.stream().map(item -> item.setDeliveryCode(finalDeliveryCode).setRegisterType(registerType).setType("2")).collect(Collectors.toList());
            detailDetailVOS.addAll(collect);
        }
        deliveryDetailService.createEntities(detailDetailVOS);
        return success;
    }

    @Override
    @Transactional
    public Boolean updateDeliveryRegister(DeliveryRegisterVO deliveryRegisterDetailVO) {
        String deliveryCode = deliveryRegisterDetailVO.getDeliveryCode();
        String registerType = deliveryRegisterDetailVO.getRegisterType();
        if (StringUtils.isEmpty(deliveryCode)) {
            throw new BusinessException("发货单号为空");
        }
        LambdaQueryWrapper<DeliveryRegister> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StringUtils.isNotEmpty(deliveryCode), DeliveryRegister::getDeliveryCode, deliveryCode).eq(DeliveryRegister::isDeleted, 0);
        List<DeliveryRegister> entityList = this.getEntityList(queryWrapper);
        if (CollectionUtils.isEmpty(entityList)) {
            throw new BusinessException("发货单号不存在,修改失败!");
        }
        boolean success = this.updateById(deliveryRegisterDetailVO);
        DeliveryProductDetailVO product = deliveryRegisterDetailVO.getProduct();
        if (ObjectUtils.isNotEmpty(product)) {
            deliveryProductService.updateEntity(product);
        }
        LambdaQueryWrapper<DeliveryDetail> detailQuery = new LambdaQueryWrapper<>();
        detailQuery.eq(DeliveryDetail::getDeliveryCode, deliveryCode);
        deliveryDetailService.deleteEntities(detailQuery);
        List<DeliveryDetail> detailDetailVOS = new ArrayList<>();
        List<DeliveryDetailDetailVO> deliveryDetails = deliveryRegisterDetailVO.getDeliveryDetail();
        if (CollectionUtils.isNotEmpty(deliveryDetails)) {
            String finalDeliveryCode = deliveryCode;
            List<DeliveryDetail> collect = deliveryDetails.stream().map(
                    item -> item.setSapContractCode(deliveryRegisterDetailVO.getSapContractCode())
                            .setSapOrderCode(deliveryRegisterDetailVO.getSapOrderCode())
                            .setDeliveryCode(finalDeliveryCode)
                            .setRegisterType(registerType)
                            .setType("1")).collect(Collectors.toList());
            detailDetailVOS.addAll(collect);
        }
        List<DeliveryDetailDetailVO> outDeliveryDetails = deliveryRegisterDetailVO.getOutDeliveryDetail();
        if (CollectionUtils.isNotEmpty(outDeliveryDetails)) {
            String finalDeliveryCode = deliveryCode;
            List<DeliveryDetail> collect = outDeliveryDetails.stream().map(
                    item -> item.setSapContractCode(deliveryRegisterDetailVO.getSapContractCode())
                            .setSapOrderCode(deliveryRegisterDetailVO.getSapOrderCode())
                            .setDeliveryCode(finalDeliveryCode)
                            .setRegisterType(registerType)
                            .setType("2")).collect(Collectors.toList());
            detailDetailVOS.addAll(collect);
        }
        deliveryDetailService.createOrUpdateEntities(detailDetailVOS);
        return success;
    }

    @Override
    @Transactional
    public Boolean deleteDeliveryRegister(String id) {
        DeliveryRegister viewObject = this.getEntity(id);
        String deliveryCode = viewObject.getDeliveryCode();

        //查询发货关联合同项目信息
        LambdaQueryWrapper<DeliveryProduct> productQw = new LambdaQueryWrapper<>();
        productQw.eq(DeliveryProduct::getDeliveryCode, deliveryCode);
        deliveryProductService.deleteEntities(productQw);

        //查询发货详情
        LambdaQueryWrapper<DeliveryDetail> detailQw = new LambdaQueryWrapper<>();
        detailQw.eq(DeliveryDetail::getDeliveryCode, deliveryCode);
        deliveryDetailService.deleteEntities(detailQw);
        return this.deleteEntity(id);
    }

    @Override
    public Boolean deleteDeliveryRegisterBatch(List<String> ids) {
        List<DeliveryRegister> entityListByIds = this.getEntityListByIds(ids);
        List<String> deliveryCodes = entityListByIds.stream().map(DeliveryRegister::getDeliveryCode).collect(Collectors.toList());

        //查询发货关联合同项目信息
        LambdaQueryWrapper<DeliveryProduct> productQw = new LambdaQueryWrapper<>();
        productQw.in(DeliveryProduct::getDeliveryCode, deliveryCodes);
        deliveryProductService.deleteEntities(productQw);

        //查询发货详情
        LambdaQueryWrapper<DeliveryDetail> detailQw = new LambdaQueryWrapper<>();
        detailQw.eq(DeliveryDetail::getDeliveryCode, deliveryCodes);
        deliveryDetailService.deleteEntities(detailQw);

        return this.deleteEntities(ids);
    }

    private String genDeliveryCode() {
        UUID uuid = UUID.randomUUID();
        String uuidStr = uuid.toString().replace("-", "");
        int randomValue = Integer.parseInt(uuidStr.substring(0, 8), 16);
        return "ab" + randomValue;
    }
}